import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk

def zoom_image():
    global img, photo
    # 缩放比例
    zoom = 0.5
    # 获取原图的宽度和高度
    old_w, old_h = img.size
    # 计算缩放后的宽度和高度
    zoom_w = int(old_w * zoom)
    zoom_h = int(old_h * zoom)

    # 创建一个新的空白图像用于存放缩放后的图像
    zoomed_img = Image.new("RGBA", (zoom_w, zoom_h))

    # 水平采样间距：原宽度/新宽度
    gap_w = old_w / zoom_w
    # 垂直采样间距：原高度/新高度
    gap_h = old_h / zoom_h
    # 采样半径
    len_h = gap_h / 2
    len_w = gap_w / 2

    # 逐行
    for h_i in range(int(gap_h - 1), old_h, int(gap_h)):
        # 逐列
        for w_i in range(int(gap_w - 1), old_w, int(gap_w)):
            # 寻找当前像素点起始与结束的坐标
            h_top = max(0, int(h_i - len_h))  # 上边起始坐标
            h_down = min(old_h - 1, int(h_i + len_h))  # 下边结束坐标
            w_left = max(0, int(w_i - len_w))  # 左边起始坐标
            w_right = min(old_w - 1, int(w_i + len_w))  # 右边结束坐标

            # 加权均值法：计算周围像素点的距离总值
            sum_dis = 0
            area = []  # 区域数组：坐标Y、坐标X、距离
            for y_top in range(h_top, h_down + 1):
                for x_left in range(w_left, w_right + 1):
                    # 三角函数计算距离，邻近插值
                    dx = abs(x_left - w_i)
                    dy = abs(y_top - h_i)
                    dis = (dx ** 2 + dy ** 2) ** 0.5
                    area.append([y_top, x_left, dis])
                    # 求和
                    sum_dis += dis

            # 通过加权平均计算颜色值
            dis_sum = 0
            for ar in area:
                # 距离权重是该坐标点与焦点的距离/选区内所有坐标点与焦点距离的总和
                dis_p = ar[2] / sum_dis
                ar[2] = dis_p
                dis_sum += dis_p

            # 初始化 RGB
            R, G, B, A = 0, 0, 0, 0
            for ar in area:
                # 权重值是该坐标点的距离权重/选区内所有坐标点距离权重值的总和
                color_p = ar[2] / dis_sum
                p_y, p_x = ar[0], ar[1]
                r, g, b, a = img.getpixel((p_x, p_y))
                R += r * color_p
                G += g * color_p
                B += b * color_p
                A += a * color_p

            zoomed_img.putpixel((int(w_i / gap_w), int(h_i / gap_h)), (int(R), int(G), int(B), int(A)))

    # 更新显示的图像
    photo = ImageTk.PhotoImage(zoomed_img)
    canvas.create_image(0, 0, anchor=tk.NW, image=photo)

def open_image():
    global img, photo
    file_path = filedialog.askopenfilename()
    if file_path:
        img = Image.open(file_path)
        photo = ImageTk.PhotoImage(img)
        canvas.create_image(0, 0, anchor=tk.NW, image=photo)

root = tk.Tk()
root.title("图像缩小")

# 创建一个按钮用于打开图像
open_button = tk.Button(root, text="打开图像", command=open_image)
open_button.pack()

# 创建一个按钮用于缩小图像
zoom_button = tk.Button(root, text="缩小图像,等待一会", command=zoom_image)
zoom_button.pack()

# 创建一个画布用于显示图像
canvas = tk.Canvas(root)
canvas.pack()

img = None
photo = None

root.mainloop()